% Sockets Galo - Luis Paulo Reis, 16 de Novembro de 2004 - corrigido para SICStus4 em Novembro de 2009

% Parte 1: Utilizacao generica de sockets para um jogo de tabuleiro

:-use_module(library(sockets)).

port(60011).

server:-
	port(Port),
	socket_server_open(Port,Socket),
	socket_server_accept(Socket, _Client, Stream, [type(text)]),
	server_loop(Stream),
	socket_server_close(Socket),
	write('Server Exit'),nl.

server_loop(Stream) :-
	repeat,
		read(Stream, ClientRequest),
		write('Received: '), write(ClientRequest), nl, 
		server_input(ClientRequest, ServerReply),
		format(Stream, '~q.~n', [ServerReply]),
		write('Send: '), write(ServerReply), nl, 
		flush_output(Stream),
	(ClientRequest == bye; ClientRequest == end_of_file), !.

server_input(initialize, ok(Board)):- 
	board(Board), !.
server_input(execute(Mov, Board), ok(NewBoard)):- 
	valid_move(Mov, Board),
	execute_move(Mov, Board, NewBoard), !.
server_input(calculate(Level, J, Board), ok(Mov, NewBoard)):- 
	calculate_move(Level, J, Board, Mov),
	execute_move(Mov, Board, NewBoard), !.
server_input(game_end(Board), ok(Winner)):- 
	end_game(Board, Winner), !.
server_input(bye, ok):-!.
server_input(end_of_file, ok):-!.
server_input(_, invalid) :- !.


% Parte 2: Exemplo de um Servidor de Jogo do Galo muito simples

:- use_module(library(lists)).

board([0,0,0,0,0,0,0,0,0]).
valid_move(_-Pos, Board):- nth(Pos,Board,0).
execute_move(J-Pos, Board, NewBoard):- change(Pos,1,J,Board,NewBoard).
calculate_move(_, J, Board, J-Pos):- nth(Pos,Board,0).

change(_, _, _, [], []).
change(Pos,Pos,Pec,[_|Re],[Pec|Re2]):- Pos2 is Pos+1, change(Pos,Pos2,Pec,Re,Re2).
change(Pos,P,Pec,[El|Re],[El|Re2]):- Pos\=P, P2 is P+1, change(Pos,P2,Pec,Re,Re2).

end_game([J,J,J,_,_,_,_,_,_],J) :- J\=0.
end_game([_,_,_,J,J,J,_,_,_],J) :- J\=0.
end_game([_,_,_,_,_,_,J,J,J],J) :- J\=0.
end_game([J,_,_,J,_,_,J,_,_],J) :- J\=0.
end_game([_,J,_,_,J,_,_,J,_],J) :- J\=0.
end_game([_,_,J,_,_,J,_,_,J],J) :- J\=0.
end_game([J,_,_,_,J,_,_,_,J],J) :- J\=0.
end_game([_,_,J,_,J,_,J,_,_],J) :- J\=0.
end_game(Board, 0):- \+memberchk(0,Board).

nth(1,[X|_],X).
nth(N,[_|R],X) :- nth(N1,R,X), N is N1+1.
